// 记录用户操作表格列宽伸缩的记录信息  兼容LocalStorage和IndexedDB 两种方式，优先使用IndexedDB
interface TableRecords {
  uid: string;
  [key: string]: any; // key: 对应表格vid, 值对应伸缩的所有列宽度数据
}
/**
 * uid: 用户id
  vid_8wtarwsqqj: {name: 298.96875, id: 50}
  .....
 */
interface UserTableRecordsDB {
  saveTableRecords(tableRecords: TableRecords, uid: string): void;
  getTableRecords(uid: string): Promise<TableRecords | {}>;
  clearTableRecords(): void;
}

class LocalStorageDB implements UserTableRecordsDB {
  private key: string;
  constructor(key: string) {
    this.key = key;
  }
  public saveTableRecords(tableRecords: TableRecords, uid: string) {
    const info = JSON.parse(localStorage.getItem(this.key) || '{}');
    info[uid] = tableRecords;
    localStorage.setItem(this.key, JSON.stringify(info));
  }

  public async getTableRecords(uid: string): Promise<TableRecords> {
    return JSON.parse(localStorage.getItem(this.key) || '{}')?.[uid] ?? {};
  }

  public clearTableRecords() {
    localStorage.removeItem(this.key);
  }
}

class IndexDB implements UserTableRecordsDB {
  private readonly dbName = 'user_table_records';
  private readonly storeName = 'table_records';
  private db: IDBDatabase | null = null;

  constructor() {
    this.initDB();
  }

  private initDB() {
    return new Promise((resolve, reject) => {
      const request = window.indexedDB.open(this.dbName, 1);

      request.onerror = (_event) => {
        reject(new Error('UserTableRecords: Failed to open indexedDB'));
      };

      request.onsuccess = (_event) => {
        this.db = request.result;
        resolve(true);
      };

      request.onupgradeneeded = (_event) => {
        const db = request.result;
        if (!db.objectStoreNames.contains(this.storeName)) {
          db.createObjectStore(this.storeName, { keyPath: 'uid' });
        }
      };
    });
  }

  public saveTableRecords(tableRecords: TableRecords) {
    if (this.db) {
      const transaction = this.db.transaction(this.storeName, 'readwrite');
      const store = transaction.objectStore(this.storeName);
      store.put(tableRecords);
    }
  }

  public async getTableRecords(uid: string): Promise<TableRecords | {}> {
    await this.initDB();
    return new Promise((resolve, reject) => {
      if (!this.db) {
        reject('UserTableRecords: IndexedDB not initialized');
        return;
      }
      const transaction = this.db.transaction(this.storeName, 'readonly');
      const store = transaction.objectStore(this.storeName);
      // 用户读取数据，参数是主键
      const request = store.get(uid);
      request.onsuccess = () => {
        if (request.result) {
          resolve(request.result);
        } else {
          resolve({});
        }
      };
      request.onerror = () => {
        reject(new Error('Failed to get tableRecords'));
      };
    });
  }

  public clearTableRecords() {
    return new Promise((resolve, reject) => {
      if (this.db) {
        const transaction = this.db.transaction(this.storeName, 'readwrite');
        const store = transaction.objectStore(this.storeName);
        const request = store.clear();
        request.onsuccess = () => {
          resolve(true);
        };
        request.onerror = () => {
          reject(new Error('Failed to clear tableRecords'));
        };
      } else {
        reject('UserTableRecords: IndexedDB not initialized');
      }
    });
  }
}

export class UserTableRecords {
  private static instance: UserTableRecords;
  private db: UserTableRecordsDB;

  private constructor() {
    this.db = this.getDB();
  }
  public static getInstance(): UserTableRecords {
    if (!UserTableRecords.instance) {
      UserTableRecords.instance = new UserTableRecords();
    }
    return UserTableRecords.instance;
  }

  private getDB(): UserTableRecordsDB {
    if (typeof window.indexedDB !== 'undefined') {
      return new IndexDB();
    } else if (typeof window.localStorage !== 'undefined') {
      return new LocalStorageDB('user_table_records');
    } else {
      return {
        saveTableRecords: () => {},
        getTableRecords: () => Promise.resolve({}),
        clearTableRecords: () => {},
      };
    }
  }

  public saveTableRecords(column: any, uid: string, tableId: string) {
    this.getTableRecords(uid).then((res) => {
      const info = res[tableId] ?? {};
      info[column.dataIndex] = column.width;
      res[tableId] = info;
      res.uid = uid;
      this.db.saveTableRecords(res, uid);
    });
  }

  public async getTableRecords(uid: string): Promise<any> {
    return this.db.getTableRecords(uid);
  }

  public clearTableRecords() {
    this.db.clearTableRecords();
  }
}

export default UserTableRecords.getInstance();
